using QntPlatform.Strategy.CmdCtrl;
using QntPlatform.Strategy.Utility;
using System;
using System.Collections.Generic;
using  QntPlatform.Strategy;

namespace QntPlatform.Strategy.S2
{
    /// <summary>
    /// 标准突破，趋势做单，只添加固定止损，不设止盈，
    /// </summary>
    [ArgInfo(Remark = @"标准突破，趋势做单，固定止损，跟踪止盈；
    仓位：Balance * 0.05m * 20 / nowPrice;
    请求内容格式：{""Period"":60,""islong"":true,""StopLoss"":1000}
    执行过程：仓位、止损，1/2止盈、保本止损、1/2追踪止盈
    ")]
    public class TuPo : PeriodTrandBase<TuPo.Info>
    {
        [ArgInfo(Remark = "固定止损率，在命令没有止损时使用")]
        public decimal FixStopLossRatio { get; set; } = 0.05m;
        //止盈第一阶段，固定止盈率
        [ArgInfo(Remark = "止盈第一阶段，固定止盈率")]
        public decimal FixedProfitRate1 { get; set; } =0.05m;

        //止盈第二阶段的滑动止盈回撤率
        [ArgInfo(Remark = "止盈第二阶段的滑动止盈回撤率")]
        public decimal StopProfitForSlideRate2 { get; set; }=0.01m;
        //止盈1时的平仓比例
        [ArgInfo(Remark = "止盈1时的平仓比例")]
        public decimal StopRateAtProfit1 { get; set; }=0.5m;
        protected override bool IsCheckTrend => false;
        public void InBuy(Info info, bool isLong = true)
        {
            //buy
            var account = Exchange.GetAccountAsync();
            var tck = Exchange.GetTickerAsync();
            var nowPrice = tck.Result.Buy;
            if (info.StopLoss != null && CalcFun.CalcProfitRate(info.StopLoss.Value, nowPrice, isLong) > 0)
            {
                Log.Warn("命令无效：止损高于购入成本:isLong=" + isLong, info);
                return;
            }
            decimal buyAmount = AmountCalc(account.Result, nowPrice);
            Log.Debug("交易准备信息", new { account.Result.Balance, nowPrice });
            var id = isLong ? Exchange.BuyAsync(buyAmount) : Exchange.SellAsync(-1, buyAmount);
            var auto = new TvCmdHandler.AutoSellOrder();
            auto.SourcePrice = nowPrice;
            //auto.ProfitPrices = cmdVal.sells;
            auto.SourceOrderId = id.Result;
            auto.SourceAmount = buyAmount;
            auto.Amount = buyAmount;
            auto.Direction = isLong ? SideDirection.CloseBuy : SideDirection.CloseSell;
            if (info.StopLoss is null)
            {
                auto.StopLossPrice = isLong ? nowPrice * (1 - FixStopLossRatio) : nowPrice * (1 + FixStopLossRatio);
                Log.Debug("止损为空，固定比例计算", new { auto.StopLossPrice });
            }
            else
            {
                auto.StopLossPrice = info.StopLoss.Value;
            }
            auto.HandlerType = nameof(BuyStop); // this.GetType().Name;
            var slinfo = new StopLoss2.StopLossInfo() { StopLossPrice = auto.StopLossPrice, IsCloseBuy = auto.Direction == SideDirection.CloseBuy, Amount = auto.Amount, SourceOrderId = auto.SourceOrderId };
            new StopLoss2(this, slinfo, nowPrice, FixedProfitRate1, StopProfitForSlideRate2, StopRateAtProfit1).TaskBegin();
            Log.Debug("突破压力，交易完成，添加止损：", auto);
        }

        private   decimal AmountCalc(Account account, decimal nowPrice)
        {
            var bl = account.Balance;
            if (Exchange is BinanceApi.DApi.USDExchangeImp)
            {
                bl = nowPrice * bl;
            }
            return bl * 0.05m * 20 / nowPrice;
        }

        public override void Execute(Info info)
        {

            if (info.IsLong.Value)
            {
                InBuy(info);
            }
            else
            {
                InBuy(info, false);
            }
        }



        public class Info : TradeInfo
        {
            public decimal? StopLoss { get; set; }

        }
    }
    public class StopLoss2
    {


        //止损数据，执行方法
        public class StopLossInfo
        {
            public decimal StopLossPrice { get; set; }
            public bool IsCloseBuy { get; set; }
            public decimal Amount { get; set; }
            public string RobotId { get; set; }
            public IConvertible SourceOrderId { get; set; }
        }

        public StrategyBase2 Parent { get; }
        public StopLossInfo Data { get; internal set; }
        public decimal InPrice { get; private set; }
        public decimal FixedProfitRate1 { get; }
        public decimal StopProfitForSlideRate2 { get; }
        public decimal StopRateAtProfit1 { get; }
        public FixedProfitAction fixedProfitAction;
        public TrailingProfitAction trailingProfitAction;


        public StopLoss2(StrategyBase2 parent, StopLossInfo info, decimal inPrice, decimal fixedProfitRate1, decimal stopProfitForSlideRate2, decimal stopRateAtProfit1)
        {
            FixedProfitRate1 = fixedProfitRate1;
            StopProfitForSlideRate2 = stopProfitForSlideRate2;
            //
            Parent = parent;
            Data = info;
            InPrice = inPrice;
            var fixedProfitPrice = CalcFun.CalcPriceByProfitRate(fixedProfitRate1, inPrice, info.IsCloseBuy);
            fixedProfitAction = new FixedProfitAction(info.IsCloseBuy, fixedProfitPrice, parent.Log);

            trailingProfitAction = new TrailingProfitAction(inPrice, info.IsCloseBuy, stopProfitForSlideRate2, fixedProfitRate1, parent.Log);
            StopRateAtProfit1 = stopRateAtProfit1;
        }

        public void TaskBegin()
        {
            Parent.Exchange.TickerChangeEvent += Exchange_TickerChangeEvent;
        }
        bool isEnd = false;
        private void Exchange_TickerChangeEvent(object sender, Ticker e)
        {
            lock (this)
            {
                if (Parent.IsEnd||(!isEnd && Execute(e)))
                {
                    isEnd = true;
                    Parent.Exchange.TickerChangeEvent -= Exchange_TickerChangeEvent;
                }
            }

        }
        int setp = 0;
        public bool Execute(Ticker tck)
        {
            //检查止损
            if (CalcFun.CalcUnitProfit(tck.Buy, Data.StopLossPrice, Data.IsCloseBuy) <= 0)
            {
                // log.Debug("止损交易", new { tck, Data });
                var id = Parent.Exchange.CreateOrder(Data.Amount, DirectionTo.CloseFor(Data.IsCloseBuy), info: new Db.LogInfo() { Info2 = "止损交易,市价" + tck.Buy, ParentActId = Data.SourceOrderId + "" });
                if (id != null)
                {
                    return true;
                }
                Parent.Log.Warn("止损交易返回值为null", Data);
                return true;
            }
            else if (setp == 0 && fixedProfitAction.Execute(tck) == true)
            {
                var am1 = Parent.Exchange.getAmount(Data.Amount * StopRateAtProfit1);
                var id = Parent.Exchange.CreateOrder(am1, DirectionTo.CloseFor(Data.IsCloseBuy), info: new Db.LogInfo() { Info2 = "固盈1交易,市价" + tck.Buy, ParentActId = Data.SourceOrderId + "" });
                if (id != null)
                {
                    setp = 1;
                    Data.StopLossPrice = InPrice;
                    Data.Amount = Parent.Exchange.getAmount(Data.Amount) - am1;
                    fixedProfitAction.Dispose();

                    return false;
                }
            }
            else if (setp == 1 && trailingProfitAction.Execute(tck) == true)
            {
                var id = Parent.Exchange.CreateOrder(Data.Amount, DirectionTo.CloseFor(Data.IsCloseBuy), info: new Db.LogInfo() { Info2 = "追盈2交易,市价" + tck.Buy, ParentActId = Data.SourceOrderId + "" });
                if (id != null)
                {
                    trailingProfitAction.Dispose();
                    return true;
                }
            }
            return false;
        }
    }
}
